﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Client
{
    public sealed class GamePlayScene: Scene
    {
        const int MAPSURFACEWIDTH = 1024;
        const int MAPSURFACEHEIGHT = 768;
        const int LONGHEIGHT_IMAGE = 35;
        const int FLASHBASE = 410;
        const int AAX = 16;
        const int SOFFX = 0;
        const int SOFFY = 0;
        const int LMX = 30;
        const int LMY = 26;

        const int MAXLIGHT = 5;

        private Texture MainGameTexture, MapSavedTexture;
        public Surface MainGameSurface, MapSurface;


        public GamePlayScene()
            : base(SceneType.PlayGame)
        {

        }

        public override void Initializer()
        {
            MainGameSurface = DirectX.Me.DirectXDevice.GetBackBuffer(0, 0, BackBufferType.Mono);

            MapSavedTexture = new Texture(DirectX.Me.DirectXDevice, MAPSURFACEWIDTH + (MirMap.UNITX * 4), MAPSURFACEHEIGHT + (MirMap.UNITY * 4), /*MAPSURFACEWIDTH + MirMap.UNITX * 4 + 30, MAPSURFACEHEIGHT + MirMap.UNITY * 4,*/
                1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
            MapSurface = MapSavedTexture.GetSurfaceLevel(0);
        }

        public override void Finalizer()
        {
            MapSurface = null;  // This is owed by MapSavedTexture it can dispose it..

            if (MapSavedTexture != null)
            {
                MapSavedTexture.Dispose();
                MapSavedTexture = null;
            }
        }

        public override void KeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Left)
            {
                MirMap.Me.UpdateMapPos(MainDlg.posX -= 1, MainDlg.posY);
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Right)
            {
                MirMap.Me.UpdateMapPos(MainDlg.posX += 1, MainDlg.posY);
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Up)
            {
                MirMap.Me.UpdateMapPos(MainDlg.posX, MainDlg.posY -= 1);
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Down)
            {
                MirMap.Me.UpdateMapPos(MainDlg.posX, MainDlg.posY += 1);
                e.Handled = true;
            }
        }

        public override void OpenScene()
        {
        }

        public override void CloseScene()
        {
        }

        public override void OpeningScene()
        {
        }


        public override void PlayScene(Sprite gameSprite)
        {
            try
            {
                // IMPORTANT! - make sure we're drawing onto the map surface.
                DirectX.Me.DirectXDevice.SetRenderTarget(0, MapSurface);

                gameSprite.Begin(SpriteFlags.AlphaBlend);
                DrawTileMap();
            }
            finally
            {
                gameSprite.End();
            }

            // okay map drawing is done so switch back to the main surface!
            DirectX.Me.DirectXDevice.SetRenderTarget(0, MainGameSurface);
            // draw the map surface onto our main surface
            DrawSavedMapSurface(gameSprite);
        }

        private void DrawTileMap()
        {
            int i, j, m, n, imgnum;
            Texture surface;

            int Rx = MainDlg.posX; // Character X
            int Ry = MainDlg.posY; // Character Y

            MirMap.Me.ClientRect.X = Rx - 9; //should be 10...
            MirMap.Me.ClientRect.Y = Ry - 10;
            MirMap.Me.ClientRect.Width = Rx + 9;
            MirMap.Me.ClientRect.Height = Ry + 8;

            MirMap.Me.UpdateMapPos(Rx, Ry);

            if ((MirMap.Me.ClientRect.Left == MirMap.Me.OldClientRect.Left) && (MirMap.Me.ClientRect.Top == MirMap.Me.OldClientRect.Top))
                return;

            MirMap.Me.OldClientRect = MirMap.Me.ClientRect;

            m = -MirMap.UNITY * 2;
            for (j = (MirMap.Me.ClientRect.Top - MirMap.Me.BlockTop - 1); j < (MirMap.Me.ClientRect.Bottom - MirMap.Me.BlockTop + 1); j++)
            {
                n = AAX + 14 - MirMap.UNITX;
                for (i = (MirMap.Me.ClientRect.Left - MirMap.Me.BlockLeft - 2); i < (MirMap.Me.ClientRect.Right - MirMap.Me.BlockLeft + 1); i++)
                {
                    if ((i >= 0) && (i < MirMap.LOGICALMAPUNIT * 3) && (j >= 0) && (j < MirMap.LOGICALMAPUNIT * 3))
                    {
                        imgnum = (MirMap.Me.MArr[i, j].BigTileImage & 0x7FFF);
                        if (imgnum > 0)
                        {
                            if ((i % 2 == 0) && (j % 2 == 0))
                            {
                                imgnum--;
                                surface = ImageLib.BigTiles[imgnum];
                                if (surface != null)
                                    DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, m, 0), Color.White);
                            }
                        }
                    }

                    n += MirMap.UNITX;
                }
                m += MirMap.UNITY;
            }


            m = -MirMap.UNITY;
            for (j = (MirMap.Me.ClientRect.Top - MirMap.Me.BlockTop - 1); j < (MirMap.Me.ClientRect.Bottom - MirMap.Me.BlockTop + 1); j++)
            {
                n = AAX + 14 - MirMap.UNITX;
                for (i = (MirMap.Me.ClientRect.Left - MirMap.Me.BlockLeft - 2); i < (MirMap.Me.ClientRect.Right - MirMap.Me.BlockLeft + 1); i++)
                {
                    if ((i >= 0) && (i < MirMap.LOGICALMAPUNIT * 3) && (j >= 0) && (j < MirMap.LOGICALMAPUNIT * 3))
                    {
                        imgnum = MirMap.Me.MArr[i, j].SmallTileImage;
                        if (imgnum > 0)
                        {
                            imgnum--;
                            surface = ImageLib.SmallTiles[imgnum];
                            if (surface != null)
                                DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, m, 0), Color.White);
                        }
                    }
                    n += MirMap.UNITX;
                }
                m += MirMap.UNITY;
            }

            DrawMapObjects();
        }

        private void DrawMapObjects()
        {
            int i, j, m, n, wunit, fridx, ani, anitick;
            int imgheight, imgwidth;
            bool blend;
            Texture surface;

            const int MainAniCount = 0; // just temp val for now
            const int drawingbottomline = 450; // just temp val for now

            

            m = -MirMap.UNITY;
            for (j = (MirMap.Me.ClientRect.Top - MirMap.Me.BlockTop); j < (MirMap.Me.ClientRect.Bottom - MirMap.Me.BlockTop + LONGHEIGHT_IMAGE); j++)
            {
                n = AAX + 14 - MirMap.UNITX;
                //*** 48*32 Å¸ÀÏÇü ¿ÀºêÁ§Æ® ±×¸®±â
                for (i = (MirMap.Me.ClientRect.Left - MirMap.Me.BlockLeft - 2); i < (MirMap.Me.ClientRect.Right - MirMap.Me.BlockLeft + 2); i++)
                {
                    if ((i >= 0) && (i < MirMap.LOGICALMAPUNIT * 3) && (j >= 0) && (j < MirMap.LOGICALMAPUNIT * 3))
                    {
                        fridx = (MirMap.Me.MArr[i, j].ObjectImage & 0x7FFF);
                        if (fridx > 0)
                        {
                            blend = false;
                            wunit = MirMap.Me.MArr[i, j].ObjectFile;
                            ani = MirMap.Me.MArr[i, j].AniFrame;
                            if ((ani & 0x80) > 0)
                            {
                                blend = true;
                                ani = ani & 0x7F;
                            }
                            if (ani > 0)
                            {
                                anitick = MirMap.Me.MArr[i, j].AniTick;
                                fridx += (MainAniCount % (ani + (ani * anitick))) / (1 + anitick);
                            }
                            if ((MirMap.Me.MArr[i, j].DoorOffset & 0x80) > 0) //¿­¸²
                            {
                                if ((MirMap.Me.MArr[i, j].DoorIndex & 0x7F) > 0) //¹®À¸·Î Ç¥½ÃµÈ °Í¸¸
                                    fridx += (MirMap.Me.MArr[i, j].DoorOffset & 0x7F); //¿­¸° ¹®
                            }
                            fridx--;
                            // ¹°Ã¼ ±×¸²

                            surface = ReturnObjectFile(wunit, fridx);
                            if (surface != null)
                            {
                                imgwidth = surface.GetLevelDescription(0).Width;
                                imgheight = surface.GetLevelDescription(0).Height;
                                if ((imgwidth == 48) && (imgheight == 32))
                                {
                                    int mmm = m + MirMap.UNITY - imgheight;
                                    if ((n + imgwidth > 0) && (n <= ClientGlobals.ScreenWidth) && (mmm + imgheight > 0) && (mmm < drawingbottomline))
                                        DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, mmm, 0), Color.White);
                                    else
                                    {
                                        if (mmm > drawingbottomline) //ºÒÇÊ¿äÇÏ°Ô ±×¸®´Â °ÍÀ» ÇÇÇÔ
                                            DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, mmm, 0), Color.White);
                                    }
                                }
                            }

                            if (!blend)
                            {
                                surface = ReturnObjectFile(wunit, fridx);
                                if (surface != null)
                                {
                                    imgwidth = surface.GetLevelDescription(0).Width;
                                    imgheight = surface.GetLevelDescription(0).Height;
                                    if ((imgwidth != 48) || (imgheight != 32))
                                    {
                                        int mmm = m + MirMap.UNITY - imgheight;
                                        if ((n + imgwidth > 0) && (n <= ClientGlobals.ScreenWidth) && (mmm + imgheight > 0) && (mmm < drawingbottomline))
                                            DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, mmm, 0), Color.White);
                                        else
                                        {
                                            if (mmm > drawingbottomline) //ºÒÇÊ¿äÇÏ°Ô ±×¸®´Â °ÍÀ» ÇÇÇÔ
                                                DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n, mmm, 0), Color.White);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                int ax = 0; int ay = 0;
                                surface = ReturnObjectFileEx(wunit, fridx, ref ax, ref ay);
                                if (surface != null)
                                {
                                    imgwidth = surface.GetLevelDescription(0).Width;
                                    imgheight = surface.GetLevelDescription(0).Height;
                                    int mmm = m + ay - 68;

                                    //DrawBlend(ObjSurface, n + ax - 2, mmm, DSurface, 1);
                                    if ((n > 0) && (mmm + imgheight > 0) && (n + imgwidth < ClientGlobals.ScreenWidth) && (mmm < drawingbottomline))
                                        DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n + ax - 2, mmm, 0), Color.White);
                                    else
                                    {
                                        if (mmm < drawingbottomline) //ºÒÇÊ¿äÇÏ°Ô ±×¸®´Â °ÍÀ» ÇÇÇÔ
                                            DirectX.Me.GameSprite.Draw(surface, Rectangle.Empty, Vector3.Empty, new Vector3(n + ax - 2, mmm, 0), Color.White);
                                    }
                                }
                            }

                        }
                    }
                    n += MirMap.UNITX;
                }
                m += MirMap.UNITY;
            }
        }

        private void DrawSavedMapSurface(Sprite gameSprite)
        {
            gameSprite.Begin(SpriteFlags.None);
            gameSprite.Draw(MapSavedTexture, Rectangle.Empty, Vector3.Empty, Vector3.Empty, Color.White);
            //gameSprite.Draw(MapSavedTexture, new Rectangle(MirMap.UNITX /*+ Myself.ShiftX*/,
            //    MirMap.UNITY /*+ Myself.ShiftY*/,
            //    /*MirMap.UNITX + + Myself.ShiftX*/ + MAPSURFACEWIDTH,
            //    /*MirMap.UNITY + Myself.ShiftY*/ + MAPSURFACEHEIGHT),
            //    Vector3.Empty, Vector3.Empty, Color.White);
            gameSprite.End();
        }

        private static Texture ReturnObjectFile(int objectIndex, int imageIndex)
        {
            switch (objectIndex)
            {
                case 0: return ImageLib.Objects1[imageIndex];
                case 1: return ImageLib.Objects2[imageIndex];
                case 2: return ImageLib.Objects3[imageIndex];
                case 3: return ImageLib.Objects4[imageIndex];
                case 4: return ImageLib.Objects5[imageIndex];
                case 5: return ImageLib.Objects6[imageIndex];
                case 6: return ImageLib.Objects7[imageIndex];
                case 7: return ImageLib.Objects8[imageIndex];
                case 8: return ImageLib.Objects9[imageIndex];
                case 9: return ImageLib.Objects10[imageIndex];
                default: return ImageLib.Objects1[imageIndex];
            }
        }

        private static Texture ReturnObjectFileEx(int objectIndex, int imageIndex, ref int posX, ref int posY)
        {
            switch (objectIndex)
            {
                case 0: return ImageLib.Objects1.GetCachedImage(imageIndex, ref posX, ref posY);
                case 1: return ImageLib.Objects2.GetCachedImage(imageIndex, ref posX, ref posY);
                case 2: return ImageLib.Objects3.GetCachedImage(imageIndex, ref posX, ref posY);
                case 3: return ImageLib.Objects4.GetCachedImage(imageIndex, ref posX, ref posY);
                case 4: return ImageLib.Objects5.GetCachedImage(imageIndex, ref posX, ref posY);
                case 5: return ImageLib.Objects6.GetCachedImage(imageIndex, ref posX, ref posY);
                case 6: return ImageLib.Objects7.GetCachedImage(imageIndex, ref posX, ref posY);
                case 7: return ImageLib.Objects8.GetCachedImage(imageIndex, ref posX, ref posY);
                case 8: return ImageLib.Objects9.GetCachedImage(imageIndex, ref posX, ref posY);
                case 9: return ImageLib.Objects10.GetCachedImage(imageIndex, ref posX, ref posY);
                default: return ImageLib.Objects1.GetCachedImage(imageIndex, ref posX, ref posY);
            }
        }
    }
}